//线程池
package goroutinePool

import (
	"fmt"
	"huayan.com/src/helper"
	"strconv"
	"sync"
)

var PoolObj *Pool         //协程池对象指针
var Wg *sync.WaitGroup //全局WaitGroup等待队列

//定义Task，将所有待处理的任务封装进去
type Task struct {
	f func() error
}

//创建一个Task任务
//@f 具体任务
func NewTask(f func() error) *Task {
	t := Task{
		f: f,
	}
	return &t
}

//Task任务开始
//@t Task指针
func (t *Task) Execute() {
	t.f()
}

//定义协程池
type Pool struct {
	EntryChannel chan *Task //等待通道，对外接收Task的入口
	worker_num   int        //最大worker的数量
	JobsChannel  chan *Task //就绪通道，池内的任务就绪队列
}

//创建池
//@cap 协程个数
//@waitBuffer 等待通道长度
//@jobsBuffer 就绪通道长度
func NewPool(cap int, waitBuffer int, jobsBuffer int) *Pool {
	p := Pool{
		EntryChannel: make(chan *Task, waitBuffer),
		worker_num:   cap,
		JobsChannel:  make(chan *Task, jobsBuffer),
	}
	Wg = &sync.WaitGroup{}
	Wg.Add(cap)
	PoolObj = &p
	return &p
}

//池创建一个worker routine，从jobsChannel里接收任务并执行。
func (this *Pool) worker(workId int) {
	Wg.Add(1)
	//接收任务
	for task := range this.JobsChannel {
		fmt.Println("worker ID", workId, "任务开始执行")
		task.Execute()
		//日志记录
		helper.WriteLog("协程处理：", "workerId:", strconv.Itoa(workId), "任务执行结束")
	}

	//日志记录
	helper.WriteLog("协程状态：", "workerId:", strconv.Itoa(workId), "协程结束")

	//routine结束
	Wg.Done()
}

//协程池初始化协程，就绪通道中从等待通道中获取任务；协程从就绪通道中获取任务。
func (this *Pool) Run() {
	//开启指定个数的goroutine
	for i := 0; i < this.worker_num; i++ {
		go this.worker(i)
	}

	//从入口channel接收任务，存入就绪队列池中
	for task := range this.EntryChannel {
		this.JobsChannel <- task
	}



	//当外界关闭EntryChannel后，关闭jobs通道，结束协程池。
	//如果不关闭，该协程池将一直监听。
	//close(this.JobsChannel)
}
